﻿using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Linq;
using System.Linq.Dynamic;
using System.Text;
using Quizz.DataRepository.Models;
using Quizz.Infrastructure;

namespace Quizz.Service.Services
{
    public class UserService : QuizzDomainService<QuizzDataContext>
    {
        public User GetById(long id)
        {
            //return this.DataContext.Users.FirstOrDefault(u => u.Id == id);
            return CompiledUserQuery.GetUserById(this.DataContext, id);
        }

        public User GetByEmail(string email)
        {
            return CompiledUserQuery.GetByEmail(this.DataContext, email);
        }

        public bool IsEmailAvailable(string email)
        {
            return GetByEmail(email) == null;
        }

        public IEnumerable<User>  GetAll()
        {
            return CompiledUserQuery.GetAllUser(this.DataContext);
        }

        public IEnumerable<User> GetByRole(long roleId)
        {
            return CompiledUserQuery.GetByRole(this.DataContext, roleId);
        }

        public void Insert(User user)
        {
            DataContext.Users.InsertOnSubmit(user);
            DataContext.SubmitChanges();
        }

        public void Update(User user)
        {
            var original = this.DataContext.Users.FirstOrDefault(u => u.Id == user.Id);

            original.FirstName = user.FirstName;
            original.LastName = user.LastName;
            //original.Email = user.Email;
            original.Password = user.Password;
            original.IsLocked = user.IsLocked;
            //original.RegisterDate = user.RegisterDate;
            original.IsDeleted = user.IsDeleted;
            original.Phone = user.Phone;
            original.Address = user.Address;
            original.Avartar = user.Avartar;
            original.Status = user.Status;
            original.RoleId = user.RoleId;

            this.DataContext.SubmitChanges();
        }

        public void Delete(User user)
        { 
            Delete(user.Id);
        }

        public bool Delete(long id)
        {
            var sql = @"UPDATE [User] SET [Status] = {0} WHERE [Id] = {1}";
            try
            {
                ExecuteCommand(sql, (int)UserStatus.Deleted, id);
                return true;
            }
            catch { return false; }
        }

        public IEnumerable<User> GetUserPage(int page, int count,string orderCol, ref int userCount)
        {
            userCount = DataContext.Users.Count();
            return DataContext.Users.Where(u => u.Status != (int)UserStatus.Deleted).OrderBy(orderCol).Skip(page * count).Take(count).ToList();
        }

        public IEnumerable<User> GetUserPage(int page, int count, string orderCol, string keyword, ref int resultCount)
        {
            var result = DataContext.Users.Where(u => u.Status != (int)UserStatus.Deleted && u.Email.Contains(keyword) || u.LastName.Contains(keyword) || u.Phone.Contains(keyword));
            resultCount = result.Count();
            return result.OrderBy(orderCol).Skip(page * count).Take(count);
        }
    }

    internal static class CompiledUserQuery
    {
        public static Func<QuizzDataContext, long, User> GetUserById =
            CompiledQuery.Compile<QuizzDataContext, long, User>((ctx, id) => ctx.Users.FirstOrDefault(u => u.Id == id));

        public static Func<QuizzDataContext, IEnumerable<User>> GetAllUser =
            CompiledQuery.Compile<QuizzDataContext, IEnumerable<User>>(ctx => ctx.Users.OrderBy(u => u.Email));

        public static Func<QuizzDataContext, string, User> GetByEmail =
            CompiledQuery.Compile<QuizzDataContext, string, User>(
                (ctx, email) => ctx.Users.FirstOrDefault(u => u.Email.Equals(email)));

        public static Func<QuizzDataContext, long, IEnumerable<User>> GetByRole =
            CompiledQuery.Compile<QuizzDataContext, long, IEnumerable<User>>(
                (ctx, role) => ctx.Users.Where(u => u.RoleId == role).OrderBy(u => u.Email));
    }
}
